package org.fing.edu.uy.esbadp.core.utils;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * 
 * @author dev
 *
 * Lista circular generica con maximo de elementos.
 */
public class CircularList<T> implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -5209929663266652411L;
	private CircularListNode<T> head = null;
    private int numberOfElements = 0;
    private CircularListNode<T> last = null; 
    private int maxElements = 1;
    
    /**
     * 
     * @param maxElements Cantidad de elementos maximo a mantener en la lista (debe ser > 0 )
     */
    public CircularList(int maxElements){
    	this.maxElements = maxElements;
    }
    
    
    /**
     * Inserta un nuevo elemento en la lista, si la lista alcanzo el maximo permitido esta descarta el prime elemento que se inserto (ultimo de la lista).
     * @param data
     */
    public void addElement(T data){
    	if(numberOfElements>=maxElements){
    		deleteLast();
    	}    	
    	insertFirst(data);
    }
           
    public List<T> elementList(){    
    	List<T> res = new LinkedList<T>();
    	return elementList(head,res);
    }
    
     
    public boolean isEmpty()
    {
        return (numberOfElements == 0);
    }

    public int getNumberOfElements()
    {
        return numberOfElements;
    }
                 
    
    public CircularListNode<T> getHead() {
		return head;
	}


	public void setHead(CircularListNode<T> head) {
		this.head = head;
	}


	public CircularListNode<T> getLast() {
		return last;
	}


	public void setLast(CircularListNode<T> last) {
		this.last = last;
	}


	public int getMaxElements() {
		return maxElements;
	}


	public void setMaxElements(int maxElements) {
		this.maxElements = maxElements;
	}


	public void setNumberOfElements(int numberOfElements) {
		this.numberOfElements = numberOfElements;
	}


	private void insertFirst(T data)
    {
        CircularListNode<T> circularListNode = new CircularListNode<T>(head,data);
        if(head!=null){
        	 this.head.setPrevious(circularListNode);
        }
       
        head = circularListNode;
        numberOfElements++;        
        if(last==null){
        	last = head;        	
        }
    }
    
    private void deleteLast(){
    	if(last!=null){
    		CircularListNode<T> secondToLast = last.getPrevious();
    		if(secondToLast!=null){
    			secondToLast.setNext(null);
    		}else{
    			head = null;
    		}
    		last = secondToLast;
    	}
    	numberOfElements--;        
    }
    

    private List<T> elementList(CircularListNode<T> elem , List<T> res ){    	
    	if(elem!=null){    	
    		res.add(elem.getData());
    		elementList(elem.getNext(),res);
    	} 
    	return res;
    } 

  
}
